#pragma once

#include "ClientInterface.h"
#include "d3dapplication.h"
#include "d3dUtil.h"
#include "DirectInput.h"
#include "Vertex.h"
#include "SoundManager.h"
#include <time.h>
#include "View.h"
#include <tchar.h>
#include "..\Shared\GalaxyMap.h"
#include "..\Shared\SectorMap.h"
#include "..\Shared\SpaceShooterObjects.h"
#include "SpaceShooterMenu.h"
#include "FloatingTextManager.h"

#define CAMERA_START_RADIUS		200
#define CAMERA_START_ROTATION	D3DX_PI
#define CAMERA_INITIAL_TARGET_X	4 * WORLD_X_SCALE
#define CAMERA_INITIAL_TARGET_Y	0
#define CAMERA_INITIAL_TARGET_Z	-4 * WORLD_Y_SCALE
#define CAMERA_GALAXY_VIEWINGANGLE	D3DX_PI/12	
#define CAMERA_SECTOR_VIEWINGANGLE	D3DX_PI/6
#define CAMERA_SPEED_ROTATION	0.004f
#define CAMERA_SPEED_ZOOM		0.05f
#define CAMERA_SPEED_MOVE		1.0f
#define CAMERA_ZOOM_MIN			100.0f
#define CAMERA_ZOOM_MAX			300.0f
#define CAMERA_TARGETX_MAX		8 * WORLD_X_SCALE
#define CAMERA_TARGETX_MIN		0 * WORLD_X_SCALE
#define CAMERA_TARGETZ_MAX		-8 * WORLD_Y_SCALE
#define CAMERA_TARGETZ_MIN		0 * WORLD_Y_SCALE

#define TEXTCOLOR_ENEMYDAMAGED	D3DCOLOR_XRGB(0, 175, 255)
#define TEXTCOLOR_ENEMYATTACKED D3DCOLOR_XRGB(0, 255, 255)
#define TEXTCOLOR_PLAYERDAMAGED D3DCOLOR_XRGB(255, 0, 0)
#define TEXTCOLOR_GENERAL		D3DCOLOR_XRGB(255, 255, 255)
#define TEXTCOLOR_PLAYERPOS		D3DCOLOR_XRGB(255, 255, 0)

#define TEXTSCALE_ENEMYATTACKED 2
#define TEXTSCALE_ENEMYDAMAGED	2
#define TEXTSCALE_PLAYERDAMAGED	1
#define TEXTSCALE_GENERAL		1
#define TEXTSCALE_PLAYERPOS		1.5f

#define RISINGTEXT_LIFETIME		4
#define RISINGTEXT_VELOCITY		D3DXVECTOR3(0, 5, 0)
#define RISINGTEXT_STARTY		18
#define RISINGTEXTHIGHER_STARTY	26
#define RISINGTEXT_SCALE		2

#define ENERGYTEXT_Y			13
#define PLAYERPOS_Y				20

#define ERRORMSG_POS			D3DXVECTOR3((float)(mD3DPP.BackBufferWidth / 2), (float)(mD3DPP.BackBufferHeight / 4), 0)
#define ERRORMSG_VEL			D3DXVECTOR3(0.0f, -20.0f, 0.0f)
#define ERRORMSG_COLOR			D3DCOLOR_XRGB(255, 0, 0)
#define ERRORMSG_SCALE			1.0f
#define ERRORMSG_LIFETIME		5

#define NOTIFYMSG_POS			D3DXVECTOR3((float)(mD3DPP.BackBufferWidth / 2), (float)(mD3DPP.BackBufferHeight / 4), 0)
#define NOTIFYMSG_VEL			D3DXVECTOR3(0.0f, 10.0f, 0.0f)
#define NOTIFYMSG_COLOR			D3DCOLOR_XRGB(0, 173, 255)
#define NOTIFYMSG_SCALE			1.0f
#define NOTIFYMSG_LIFETIME		5

#define MESSAGE_DELAY			1.0f

#define SHUTDOWN_WAITTIME		3.0f

class SpaceShooterClient : public d3dapplication
{
enum GameState
{
	GAMESTATE_GETIPADDRESS,	// game initializes, waiting for the user to enter an IP address
	GAMESTATE_PLAY,			// game is playing
	GAMESTATE_SHUTTINGDOWN	// game is shutting down due to some error (usually the wrong IP address or server is down)
};

public:
	SpaceShooterClient(HINSTANCE hInstance, std::string caption, D3DDEVTYPE devType, DWORD requestedVP);
	~SpaceShooterClient();

	// overriding the base class virtual functions
	// these are blank in the base class (since it doesn't do anything
	// but initialize devices), so we need to define their behaviour here
	bool checkDeviceCaps();
	void OnLostDevice();
	void OnResetDevice();
	void Update(float dt);
	void CheckInput(float dt) ;
	void Render();

	// Loads game assets during initialization
	void LoadAssets(void);

	// gets a world picking ray based on where the mouse was clicked
	D3DXVECTOR3 GetWorldPickingRay(void);

	// draws useful debug text to the screen
	void DrawDebugText(void);

	// loads all meshes into the game
	void LoadMeshes(void);
	// run View initialization functions
	void InitializeView(void);
	
	// creates the font the game will use
	void CreateFont(void);

	// initializes game variables
	void InitializeGameVariables(void);

	// gets a message from another object (e.g. a UI button)
	// to send a message to the server
	void Event(MessageType msgType);

	// processes the received message
	void ProcessMessage(Message* msg);

	// gets the current player status
	PlayerInformation GetPlayerInfo(void) {return mPlayerInfo;};

	// renders the grid components and other misc stuff
	void RenderGalaxyGridComponents(int x, int y);
	void RenderSectorGridComponents(int x, int y);
	void RenderPathToCursor(void);
	void RenderHoverText(GameObject* obj, int x, int y);

	// Galaxy map functions
	bool GalaxyMapOpen(void) {return mGalMapOpen;};
	void OpenGalaxyMap(void) {mGalMapOpen = true;};
	void CloseGalaxyMap(void) {mGalMapOpen = false;};

	// functions for getting the IP address to connect to
	void GetIPAddressUpdate();
	void GetIPAddressRender();

	// update the camera's position
	void UpdateCameraPosition();

private:
	// D3DX elements
	ID3DXSprite*	mpD3DSprite;	// used to draw sprites
	ID3DXFont*		mpD3DFont;		// Basic font

	GalaxyMap		mGalaxyMap;		// galaxymap
	SectorMap		mSectorMap;		// sectormap

	bool			mGalMapOpen;	// whether or not the galaxy map is open		

	//////////////////////
	// Camera variables
	//////////////////////
	float			mCameraRotationY;	// camera rotation
	float			mCameraRadius;		// camera radius from center
	D3DXVECTOR3		mCameraTarget;		// camera target
	
	float			mGalaxyCameraRotationY;	// galaxy map camera rotation
	float			mGalaxyCameraRadius;	// galaxy map radius
	D3DXVECTOR3		mGalaxyCameraTarget;	// target for galaxy map

	D3DXVECTOR3		mCameraUp;			// up vector


	////////////////////
	// UI and input
	////////////////////
	bool			mLMBPressed;	// checks if the LMB was pressed
	bool			mLMBReady;		// checks if the LMB is ready to be clicked

	bool			mUIEnabled;		// checks whether we're still waiting for messages from the server or not

	SpaceShooterMenu*	mUI;		// UI buttons for SpaceShooter game

	Coordinate		mMouseCoordinate; // used to check if we need to perform the A* algorithm again

	///////////////////
	// Game specific
	///////////////////
	std::vector<Node*>	mHighlightPath; // list of nodes to keep track of the current path to highlight

	PlayerInformation mPlayerInfo;	// struct to store the player's current state

	void CreateObject(ObjectType type, int x, int y);
	void CreateObject(ObjectType type, Coordinate c) {CreateObject(type, c.x, c.y);};
	
	// current delays for each message type
	float		mErrorMessageDelay;
	float		mNotifyMessageDelay;

	GameState	mState;

	string		mIPAddress;	// used to read in the IP address to connect to
};

extern SpaceShooterClient* gGame;